# -*- coding: iso-8859-1 -*-
#
#    This is part of Malvinas Argentinas Messenger
#
#    Malvinas Argentinas Messenger is free software; you can redistribute
#    it and/or modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; either version 2 of the
#    License, or (at your option) any later version.
#
#    Malvinas Argentinas Messenger is distributed in the hope that it will be
#    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Malvinas Argentinas Messenger; if not, write to the Free
#    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
#    MA  02110-1301  USA

import string
import random
import msnlib, msnp2p
import base64

class transferList:
	def __init__ (self):
		self.list = []

	def append(self, transfer):
		self.list.append(transfer)

	def hasSessionID(self, sessionID):
		found = 0
		for t in self.list:
			if t.sessionID == sessionID:
				found = 1
				break
		return found
	
	def getTransfer(self, sessionID):
		for t in self.list:
			if t.sessionID == sessionID:
				return t
				break

	def delTransfer(self, sessionID):
		for t in self.list:
			if t.sessionID == sessionID:
				self.remove(t)

class transfer:
	def __init__(self, sessionID, status, filename, size, percentComp, sizeComp, lastMsgtime, speed):
		self.sessionID = sessionID
		self.status = status
		self.filename = filename
		self.size = size
		self.percentComp = percentComp
		self.sizeComp = sizeComp
		self.lastMsgtime = lastMsgtime
		self.speed = speed

class ftManager:
	def __init__(self, mam, tid, message, nd):
		tid_copy = tid
		message_copy = message
		self.sessionID = message.split("SessionID: ")[1].split("\r\n")[0]
		if not mam.ft.hasSessionID(self.sessionID):
			mam.ft.append(Base(mam, tid, message, nd, self.sessionID))
		self.ft = mam.ft.getTransfer(self.sessionID)
		#try:
		self.ft.process(tid, message)
		#except:
			#mam.ui.padArray.addstr('EVENTS', '\nError in File transfer. Please, let know about this error.', mam.ui.COLORS.RED_R)
			#msnlib.debug('\tERROR in File transfer\n')
			#mam.ui.padArray.refresh('EVENTS')

class Base:
	GOT_INV = 1
	UPLOADING = 2
	DOWNLOADING = 3
	CANCELLED = 4	
	
	def __init__(self, mam, tid, message, nd, sessionID):
		self.mam = mam			# The system
		self.tid = tid			# The MSG dudeam@hotmail.com D... line
		self.message = message	# The following lines including the binary str
		self.nd = nd			# The socket
		self.receiver = ''		# The one who wants to send us something or the one who'll get our file

		self.identifier = self.generateRandomNumber(50000)
		self.baseID = self.identifier
		self.sessionID = sessionID
		# Msg and binary header		
		self.params = ''
		self.header = ''
		# Some info from invitation content
		self.Via = ''
		self.CallID = ''
		# Last binary header sent
		self.myLastHeader = msnp2p.BinHeader()
		self.status = self.GOT_INV

	def getFileSize(self, message):
		binary = base64.b64decode(message.split('Context: ')[1])[7:14]
		value = (int(binary[3])<<24) + (int(binary[2])<<16) + (int(binary[1])<<8) + int(binary[0])

	def getParameters(self, s):
		'''parse a message and create and return a dict with the values'''
		d = {}
		try:
			header = s.split('\r\n\r\n')[1][:48]
			d['header'] = header
		except:
			pass        
		for i in s.split('\r\n'):
			l = i.split(': ')
			if len(l) == 2:
				d[l[0]] = l[1]
		return d

	def extractViaBranch(self):
		"""try to extract the via id from the invite message return empty string otherwise """
		try:
			return self.message.split("Via: MSNSLP/1.0/TLP ;branch={")[1].split("}")[0]
		except:
			return ""
	
	def extractCallID(self):
		"""try to extract the callID from the invite message return empty string otherwise """
		try:
			return self.message.split("Call-ID: {")[1].split("}")[0]
		except:
			return ""

	def extractSessionID(self):
		"""try to extract the sessionID from the invite message return an empty string otherwise"""
		try:
			return self.message.split("SessionID: ")[1].split("\r\n")[0]
		except:
			return ""

	def nextBaseID(self):
		if self.baseID == self.identifier:
			self.baseID -= 3
		else:
			self.baseID += 1
			if self.baseID == self.identifier:
				self.baseID += 1

	def generateRandomNumber(self, min = 0, max = 2147483647):
		return random.randint(min, max)

	def isNewInvite(self, message):
		if (self.status == self.GOT_INV):
			return 1
		else:
			return 0

	def sendAccept(self):
		# msg header
		msgHeader = "MIME-Version: 1.0\r\n"
		msgHeader += "Content-Type: application/x-msnmsgrp2p\r\n"
		msgHeader += "P2P-Dest: "+ self.receiver + "\r\n\r\n"

		# binary header
		header = msnp2p.BinHeader()
		header.setIdentifier(self.baseID)
		self.nextBaseID()
		#header.setTotalDataSize(bin.getTotalDataSize())
		#header.setFlag(int(0x2))
		#header.setAcknowledgedIdentifier(bin.getIdentifier())
		header.setAcknowledgedIdentifier(self.generateRandomNumber())
		#header.setAcknowledgedUniqueID(bin.getAcknowledgedIdentifier())
		#header.setAcknowledgedDataSize(bin.getTotalDataSize())

		# we save last binary header sent
		self.myLastHeader = header

		# body
		s = 'MSNSLP/1.0 200 OK\r\n'
		s += 'To: <msnmsgr:' + self.receiver + '>\r\n'
		s += 'From: <msnmsgr:' + self.mam.m.email + '>\r\n'
		s += 'Via: MSNSLP/1.0/TLP ;branch={' + self.Via + '}\r\n'
		s += 'CSeq: 1 \r\n'
		s += 'Call-ID: {' + self.CallID + '}\r\n'
		s += 'Max-Forwards: 0\r\n'
		s += 'Content-Type: application/x-msnmsgr-sessionreqbody\r\n'
		content = 'SessionID: ' + str(self.sessionID) + '\r\n\r\n\0'
		s += 'Content-Length: ' + str(len(content)) + '\r\n\r\n'		
		s += content
		header.setTotalDataSize(len(s))
		header.setMessageLength(len(s))
		
		# send msg
		tid = self.nd.get_tid()
		self.nd.fd.send('MSG ' + str(tid) + ' D ' + \
		str(len(msgHeader)+52+len(s)) + '\r\n' + msgHeader + header.getData() + s + \
		'\0\0\0\0')
		msnlib.debug('\n' + str(msgHeader) + '\n' + header.printFields() + s)
		self.status = self.DOWNLOADING

	def process(self, tid, message):
		self.tid = tid			# The MSG dudeam@hotmail.com D... line
		self.message = message	# The following lines including the binary str

		# Build the binary header received
		self.params = self.getParameters(self.message)
		self.header = msnp2p.BinHeader(self.params['header'])
		tid_copy = self.tid
		self.receiver = tid_copy.split(' ')[0]
		
		# debugging
		msnlib.debug('RECIBIDO:\n' + self.header.printFields())
		msnlib.debug('BIN RECIBIDO:\n')
		for i in self.header:
			msnlib.debug(str(i) + ' ', 1)
		if self.isNewInvite(self.message):
			msnlib.debug('MSG IS NEW FILE TRANSFER INVITATION !!!\n\n')
			#msnlib.debug('Context: %s\n' % str(self.getFileSize(self.message)))
			# Set some content parsing
			self.sessionID = self.extractSessionID()
			self.Via = self.extractViaBranch()
			self.CallID = self.extractCallID()
			# Send accept msg
			self.sendAccept()
